home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / jaq / dist / indx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-23  |  24.5 KB  |  975 lines

  1. /* 
  2.  * indx.c --
  3.  *
  4.  *    Perform indexing on Jaquith archive system.
  5.  *
  6.  * Copyright 1992 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/lib/forms/RCS/indx.c,v 1.0 91/01/07 18:02:37 mottsmth Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include "jaquith.h"
  21.  
  22. #define DEF_DIR_PERM 0755
  23. #define DEF_FILE_PERM 0644
  24. #define DEF_TAB_SIZE 277      /* arbitrary. Table will grow as needed */
  25.  
  26. #define SLASHSUFFIX "slash"
  27. #define FILESUFFIX "_jaquith.files"
  28. #define INDX_VERSION 1
  29.  
  30. extern int jDebug;
  31. extern int syserr;
  32.  
  33. static int  MatchPath      _ARGS_ ((char **partList,
  34.                     char *dirPath,
  35.                     Q_Handle *indxQueue));
  36. static int  IsReadable     _ARGS_ ((T_FileStat *statInfoPtr,
  37.                     Caller *callerPtr));
  38. static int  ReadIndxFile   _ARGS_ ((char *path, T_FileStat **listPtr,
  39.                     int *cntPtr));
  40. static char *ReadStringItem _ARGS_ ((FILE *indxStream));
  41.  
  42.  
  43.  
  44. /*
  45.  *----------------------------------------------------------------------
  46.  *
  47.  * Indx_Open --
  48.  *
  49.  *    Locate and open an index buffer file
  50.  *
  51.  * Results:
  52.  *    stream ptr or NULL
  53.  *
  54.  * Side effects:
  55.  *    Consumes a file descriptor.
  56.  *      Preserve name of current open file.
  57.  *
  58.  * Note:
  59.  *      All the directories leading to the file are created
  60.  *      as necessary.
  61.  *
  62.  *----------------------------------------------------------------------
  63.  */
  64.  
  65. int
  66. Indx_Open(pathName, openOptions, indxStrPtr)
  67.     char *pathName;           /* name of index file */
  68.     char *openOptions;        /* read, write, etc. */
  69.     FILE **indxStrPtr;        /* receiving object */
  70. {
  71.     char *curPtr;
  72.  
  73.     /*
  74.      * First, be optimistic...
  75.      */
  76.     if ((*indxStrPtr=fopen(pathName, openOptions)) != (FILE *)NULL) {
  77.     return T_SUCCESS;
  78.     } else if (errno != ENOENT) {
  79.     syserr = errno;
  80.     fprintf(stderr,"Indx_Open: couldn't open %s; eno %d\n",
  81.         pathName,syserr);
  82.     return T_INDXFAILED;
  83.     } else if (*openOptions == 'r') {
  84.     return T_SUCCESS;
  85.     }
  86.     
  87.     /*
  88.      * some part of the path is not there and we're writing...
  89.      */
  90.     curPtr = pathName;
  91.     
  92.     while (curPtr != NULL) {
  93.     curPtr = STRCHR(curPtr+1, '/');
  94.     *curPtr = '\0';
  95.     if (access(pathName, X_OK) == -1) {
  96.         break;
  97.     }
  98.     *curPtr = '/';
  99.     } 
  100.  
  101.     while (curPtr != NULL) {
  102.     *curPtr = '\0';
  103.     if (mkdir(pathName, DEF_DIR_PERM) == -1) {
  104.         syserr = errno;
  105.         return T_INDXFAILED;
  106.     }
  107.     *curPtr = '/';
  108.     curPtr = STRCHR(curPtr+1, '/');
  109.     } 
  110.  
  111.     /*
  112.      * Now retry the open
  113.      */
  114.     if ((*indxStrPtr=fopen(pathName, openOptions)) == (FILE *)NULL) {
  115.     syserr = errno;
  116.     fprintf(stderr,"Indx_Open: open failed %d\n", errno);
  117.     return T_INDXFAILED;
  118.     }
  119.  
  120.     return T_SUCCESS;
  121.  
  122. }
  123.  
  124.  
  125.  
  126. /*
  127.  *----------------------------------------------------------------------
  128.  *
  129.  * Indx_Close --
  130.  *
  131.  *    Close an index file
  132.  *
  133.  * Results:
  134.  *    none.
  135.  *
  136.  * Side effects:
  137.  *    none.
  138.  *
  139.  *----------------------------------------------------------------------
  140.  */
  141.  
  142. int
  143. Indx_Close(indxStream)
  144.     FILE *indxStream;         /* open index stream */
  145. {
  146.     if (indxStream != (FILE *)NULL) {
  147.     fclose(indxStream);
  148.     }
  149.     return T_SUCCESS;
  150. }
  151.  
  152.  
  153.  
  154. /*
  155.  *----------------------------------------------------------------------
  156.  *
  157.  * Indx_ReadIndxEntry --
  158.  *
  159.  *    Parse an entry from an indx file.
  160.  *
  161.  * Results:
  162.  *    returns T_FileStat.
  163.  *
  164.  * Side effects:
  165.  *      May allocate some space. Will read indx file.
  166.  *
  167.  * Note:
  168.  *      Each string item in the index record is preceded by a length.
  169.  *      This is necessary since Unix filenames can have arbitrary characters
  170.  *      in them. (Everything except '\0', ' ', and '/', I think).
  171.  *
  172.  *----------------------------------------------------------------------
  173.  */
  174.  
  175. int
  176. Indx_ReadIndxEntry(indxStream, statInfoPtr)
  177.     FILE *indxStream;         /* source stream */
  178.     T_FileStat *statInfoPtr;  /* receiving structure */
  179. {
  180.     int version;
  181.  
  182.     /*
  183.      * if this read fails, we'll assume we're reading the last
  184.      * (incomplete) entry and say we're done.
  185.      */
  186.     if (fscanf(indxStream, "%x", &version) != 1) {
  187.     return T_FAILURE;
  188.     }
  189.  
  190.     /*
  191.      * opportunity here to do special processing depending 
  192.      * on version number, if it ever becomes necessary.
  193.      */
  194.     if (version != INDX_VERSION) {
  195.     if (jDebug) {
  196.         fprintf(stderr,"Indx_ReadIndxEntry: Bad index version: 0x%0x\n",
  197.             version);
  198.     }
  199.     return T_BUFFAILED;
  200.     }
  201.  
  202.     if (fscanf(indxStream, "%x %x %x %x %x %x %x\n",
  203.             &statInfoPtr->size,
  204.             &statInfoPtr->mode,
  205.             &statInfoPtr->atime,
  206.             &statInfoPtr->mtime,
  207.             &statInfoPtr->vtime,
  208.             &statInfoPtr->tBufId,
  209.             &statInfoPtr->offset) != 7) {
  210.     if (jDebug) {
  211.         fprintf(stderr,"Didn't get numbers\n");
  212.     }
  213.     return T_BUFFAILED;
  214.     }
  215.  
  216.     if ((statInfoPtr->fileName=ReadStringItem(indxStream)) == NULL) {
  217.     if (jDebug) {
  218.         fprintf(stderr,"Didn't get filename\n");
  219.     }
  220.     return T_BUFFAILED;
  221.     }
  222.     if ((statInfoPtr->uname=ReadStringItem(indxStream)) == NULL) {
  223.     if (jDebug) {
  224.         fprintf(stderr,"Didn't get uname\n");
  225.     }
  226.     return T_BUFFAILED;
  227.     }
  228.     if ((statInfoPtr->gname=ReadStringItem(indxStream)) == NULL) {
  229.     if (jDebug) {
  230.         fprintf(stderr,"Didn't get gname\n");
  231.     }
  232.     return T_BUFFAILED;
  233.     }
  234.     if ((statInfoPtr->linkName=ReadStringItem(indxStream)) == NULL) {
  235.     if (jDebug) {
  236.         fprintf(stderr,"Didn't get linkname\n");
  237.     }
  238.     return T_BUFFAILED;
  239.     }
  240.     if ((statInfoPtr->abstract=ReadStringItem(indxStream)) == NULL) {
  241.     if (jDebug) {
  242.         fprintf(stderr,"Didn't get file abstract\n");
  243.     }
  244.     return T_BUFFAILED;
  245.     }
  246.     if ((statInfoPtr->fileList=ReadStringItem(indxStream)) == NULL) {
  247.     if (jDebug) {
  248.         fprintf(stderr,"Didn't get file list\n");
  249.     }
  250.     return T_BUFFAILED;
  251.     }
  252.  
  253.     return T_SUCCESS;
  254. }
  255.  
  256.  
  257.  
  258. /*
  259.  *----------------------------------------------------------------------
  260.  *
  261.  * Indx_WriteEntry --
  262.  *
  263.  *    Format an entry for the index buffer and write it out, maybe twice.
  264.  *
  265.  * Results:
  266.  *    none.
  267.  *
  268.  * Side effects:
  269.  *    May write to either thdr file or indx file or both.
  270.  *
  271.  * Note:
  272.  *      There's no locking because the switchboard process is
  273.  *      only creating 1 writer at a time to an archive. Readers
  274.  *      may see an incomplete write at the end of the file and
  275.  *      ignore it.
  276.  *
  277.  *
  278.  *----------------------------------------------------------------------
  279.  */
  280.  
  281. int
  282. Indx_WriteIndxEntry(statInfoPtr, tHdrStream, indxStream)
  283.     T_FileStat *statInfoPtr;  /* meta-info for new entry */
  284.     int tHdrStream;           /* thdr file stream */
  285.     FILE *indxStream;         /* disk indx file stream */
  286. {
  287.     char *tmpPtr;
  288.     static char *bufPtr;
  289.     static int bufLen = 0;
  290.     char numBuf[8*10];
  291.     int len;
  292.     int numLen;
  293.     int fnameLen;
  294.     int linkLen;
  295.     int absLen;
  296.     int flistLen;
  297.     int unameLen;
  298.     int gnameLen;
  299.  
  300.     fnameLen = strlen(statInfoPtr->fileName);
  301.     unameLen = strlen(statInfoPtr->uname);
  302.     gnameLen = strlen(statInfoPtr->gname);
  303.     linkLen = strlen(statInfoPtr->linkName);
  304.     flistLen = strlen(statInfoPtr->fileList);
  305.     absLen = strlen(statInfoPtr->abstract);
  306.  
  307.     len = fnameLen + linkLen + absLen + flistLen + unameLen + gnameLen +
  308.     (6*10); /* space for the lengths of the six strings */
  309.  
  310.     if (len > bufLen) {
  311.     if (bufLen > 0) {
  312.         MEM_FREE("Indx_MakeEntry", bufPtr);
  313.     }
  314.     bufLen = len;
  315.     bufPtr = (char *)MEM_ALLOC("Indx_MakeEntry", len*sizeof(char));
  316.     }
  317.  
  318.    sprintf(numBuf, "%x %x %x %x %x %x %x %x\n",
  319.        INDX_VERSION,
  320.        statInfoPtr->size,
  321.        statInfoPtr->mode,
  322.        statInfoPtr->atime,
  323.        statInfoPtr->mtime,
  324.        statInfoPtr->vtime,
  325.        statInfoPtr->tBufId,
  326.        statInfoPtr->offset);
  327.     numLen = strlen(numBuf);
  328.  
  329.    /*
  330.     *  Must be careful about printf on Ultrix 4.2 because it truncates
  331.     *  strings to 32K. Large directories may have a fileList > 32K
  332.     */
  333.    sprintf(bufPtr, "%x %s\n%x %s\n%x %s\n%x %s\n%x %s\n%x ",
  334.        fnameLen, statInfoPtr->fileName,
  335.        unameLen, statInfoPtr->uname,
  336.        gnameLen, statInfoPtr->gname,
  337.        linkLen, statInfoPtr->linkName,
  338.        absLen, statInfoPtr->abstract,
  339.        flistLen);
  340.  
  341.     tmpPtr = bufPtr+strlen(bufPtr);
  342.     strcpy(tmpPtr, statInfoPtr->fileList);
  343.     tmpPtr += flistLen;
  344.     *tmpPtr++ = '\n';
  345.     *tmpPtr = '\0';
  346.     len = tmpPtr-bufPtr;
  347.  
  348.     /* write out thdr stream, if requested */
  349.     if (tHdrStream >= 0) {
  350.     write(tHdrStream, numBuf, numLen);
  351.     write(tHdrStream, bufPtr, len);
  352.     }
  353.  
  354.     /* write out indx file stream, if requested (with simple filename) */ 
  355.     if (indxStream != (FILE *)NULL) {
  356.     fwrite(numBuf, sizeof(char), numLen, indxStream);
  357.     if (fnameLen == 1) {
  358.         fprintf(indxStream, "%x %s\n", strlen(SLASHSUFFIX), SLASHSUFFIX);
  359.     } else {
  360.         tmpPtr = STRRCHR(statInfoPtr->fileName, '/') + 1;
  361.         fprintf(indxStream, "%x %s\n", strlen(tmpPtr), tmpPtr);
  362.     }
  363.     tmpPtr = STRCHR(bufPtr, '\n') + 1;
  364.     fputs(tmpPtr, indxStream);
  365.     }
  366.  
  367.     /*
  368.      * If the buffer is excessively large then assume it's a fluke
  369.      * and free it. We'll get a more reasonable one next time.
  370.      */
  371.     if (bufLen > 32*1024) {
  372.     bufLen = 0;
  373.     MEM_FREE("Indx_MakeEntry", bufPtr);
  374.     }
  375.  
  376.     return numLen+len;
  377.  
  378. }
  379.  
  380.  
  381. /*
  382.  *----------------------------------------------------------------------
  383.  *
  384.  * Indx_Match
  385.  *
  386.  *    Find all entries in a index file that match the pattern
  387.  *
  388.  * Results:
  389.  *    none.
  390.  *
  391.  * Side effects:
  392.  *    none.
  393.  *
  394.  * Note:
  395.  *      The algorithm is convoluted. We don't know ahead of time
  396.  *      how many versions of a file there are but we need the
  397.  *      second-to-last, say. So for each file that matches all
  398.  *      the other criteria, we'll keep a list of how many times
  399.  *      we seen this thing. Then after we've been through the
  400.  *      entire indx file, we'll grab the correct version(s) off
  401.  *      the file queue.
  402.  *
  403.  *----------------------------------------------------------------------
  404.  */
  405.  
  406. int
  407. Indx_Match(fileSpecPtr, indxPath, archPath, callerPtr,
  408.        receiveProc, receiveBlkPtr, ignoreDir)
  409.     QuerySpec *fileSpecPtr;   /* user specifications to be matched */
  410.     char *indxPath;           /* indx path name */
  411.     char *archPath;           /* current archive path name */
  412.     Caller *callerPtr;        /* caller's identity */
  413.     int (*receiveProc)();     /* Callback routine */
  414.     int *receiveBlkPtr;       /* Callback datum */
  415.     int ignoreDir;            /* Ignore directory. We want its contents */
  416. {
  417.     int retCode = T_SUCCESS;
  418.     char curPath[2*T_MAXPATHLEN];
  419.     int i;
  420.     int fileCnt;
  421.     T_FileStat *fileList;
  422.     T_FileStat *statInfoPtr;
  423.     T_FileStat *newInfoPtr;
  424.     time_t tmpDate;
  425.     QuerySpec newSpec;
  426.     char newIndx[2*T_MAXPATHLEN];
  427.     int first;
  428.     int last;
  429.     char *tmpPtr;
  430.     int isReadable;
  431.     Q_Handle *fileQueue;
  432.     Hash_Handle *nameTab = NULL;
  433.     int versionCnt;
  434.  
  435. /*
  436.     if (jDebug) {
  437.     fprintf(stderr,"indx_match: pattern %s, indx %s, recurse %d\n",
  438.         fileSpecPtr->fileName, indxPath, fileSpecPtr->recurse);
  439.     }
  440. */
  441.     /* Read file and convert to an array of entries */
  442.     if (ReadIndxFile(indxPath, &fileList, &fileCnt) != T_SUCCESS) {
  443.     return T_FAILURE;
  444.     } else if (fileCnt == 0) {
  445.     return T_SUCCESS;
  446.     }
  447.  
  448.     fileQueue = Q_Create("file", 1);
  449.  
  450.     if ((nameTab=Hash_Create("name", DEF_TAB_SIZE, Utils_StringHashProc, 0)) ==
  451.     (Hash_Handle *)NULL) {
  452.     return T_INDXFAILED;
  453.     }
  454.  
  455.     if (*fileSpecPtr->fileName) {
  456.     strcpy(curPath,indxPath+strlen(archPath)+sizeof(SLASHSUFFIX));
  457.     *(STRRCHR(curPath, '/')+1) = '\0';
  458.     } else {
  459.     fileSpecPtr->fileName = Str_Dup(SLASHSUFFIX);
  460.     *curPath = '\0';
  461.     }
  462.  
  463.     for (i=0, statInfoPtr=fileList;i<fileCnt; i++,statInfoPtr++) {
  464.     if (fileSpecPtr->flags & QUERY_MODDATE) {
  465.         tmpDate = statInfoPtr->mtime;
  466.     } else {
  467.         tmpDate = statInfoPtr->vtime;
  468.     }
  469.  
  470.     /* ok, put it through the tests...*/
  471.     if (((*fileSpecPtr->owner) &&
  472.          (strcmp(statInfoPtr->uname, fileSpecPtr->owner) != 0)) ||
  473.         ((*fileSpecPtr->group) &&
  474.          (strcmp(statInfoPtr->gname, fileSpecPtr->group) != 0)) ||
  475.         ((fileSpecPtr->compAbstract != NULL) &&
  476.          (!regexec(fileSpecPtr->compAbstract,statInfoPtr->abstract))) ||
  477.         ((fileSpecPtr->firstDate != -1) &&
  478.          (Time_Compare(tmpDate,fileSpecPtr->firstDate,0) < 0)) ||
  479.         ((fileSpecPtr->lastDate != -1) &&
  480.          (Time_Compare(tmpDate,fileSpecPtr->lastDate,0) > 0)) ||
  481.         ((*fileSpecPtr->fileName) &&
  482.          (!Str_Match(statInfoPtr->fileName,fileSpecPtr->fileName))) ||
  483.         ((!(isReadable=IsReadable(statInfoPtr, callerPtr))) &&
  484.          (!(S_ISADIR(statInfoPtr->mode))))) {
  485.         continue;
  486.     }
  487.  
  488.     /* Update hash table count. We'll use filemark as counter. Sorry. */
  489.     if (Hash_Lookup(nameTab, statInfoPtr->fileName,
  490.         strlen(statInfoPtr->fileName),
  491.         (Hash_ClientData *)&statInfoPtr->filemark) == T_SUCCESS) {
  492.         statInfoPtr->filemark++;
  493.         if (Hash_Update(nameTab, statInfoPtr->fileName,
  494.         strlen(statInfoPtr->fileName),
  495.         (Hash_ClientData)statInfoPtr->filemark) != T_SUCCESS) {
  496.         return T_INDXFAILED;
  497.         }
  498.     } else {
  499.         statInfoPtr->filemark = 1;
  500.         if (Hash_Insert(nameTab, statInfoPtr->fileName,
  501.         strlen(statInfoPtr->fileName),
  502.         (Hash_ClientData)statInfoPtr->filemark) != T_SUCCESS) {
  503.         return T_INDXFAILED;
  504.         }
  505.     }
  506.  
  507.     newInfoPtr = Utils_CopyFileStat(statInfoPtr);
  508.         Q_Add(fileQueue, (Q_ClientData)newInfoPtr, newInfoPtr->tBufId);
  509. /*
  510.     if (jDebug) {
  511.         fprintf(stderr,"Indx_Match: Enqueued %x %s\n",
  512.             newInfoPtr, newInfoPtr->fileName);
  513.     }
  514. */
  515.     }
  516.  
  517.     /*
  518.      * Ok, we've acquired all the entries at this level.
  519.      * Now prune them by version, and recurse where necessary.
  520.      */
  521.     fileCnt = Q_Count(fileQueue);
  522. /*
  523.     if (jDebug) {
  524.         fprintf(stderr,"Checking %d files\n", fileCnt);
  525.     }
  526. */
  527.     for (i=0; (i < fileCnt) && (retCode == T_SUCCESS); i++) {
  528.         statInfoPtr = (T_FileStat *) Q_Remove(fileQueue);
  529.     tmpPtr = statInfoPtr->fileName;
  530.     if (Hash_Lookup(nameTab, statInfoPtr->fileName,
  531.             strlen(statInfoPtr->fileName),
  532.             (Hash_ClientData *)&versionCnt)  != T_SUCCESS) {
  533.         fprintf(stderr,"Indx_Match: Couldn't look up %s\n", statInfoPtr->gname);
  534.         return T_INDXFAILED; /* shouldn't happen */
  535.     }
  536.  
  537.     if (fileSpecPtr->firstVer < 0) {
  538.         first = versionCnt + fileSpecPtr->firstVer + 1;
  539.     } else {
  540.         first = fileSpecPtr->firstVer;
  541.     }
  542.     if (fileSpecPtr->lastVer < 0) {
  543.         last = versionCnt + fileSpecPtr->lastVer + 1;
  544.     } else {
  545.         last = fileSpecPtr->lastVer;
  546.     }
  547. /*
  548.     fprintf(stderr,"first %d, last %d, cnt %d, this %d\n",
  549.         first, last, versionCnt, statInfoPtr->filemark);
  550. */
  551.     if ((statInfoPtr->filemark < first) ||
  552.         (statInfoPtr->filemark > last)) {
  553. /*
  554.         if (jDebug) {
  555.         fprintf(stderr,"Indx_Match: pruning %s\n",
  556.         statInfoPtr->fileName);
  557.         }
  558. */
  559.         Utils_FreeFileStat(statInfoPtr, 1);
  560.         continue;
  561.     }
  562.  
  563.         /* Hack: If it's a directory and we're at the top level */
  564.         /* then don't return it; we're just interested in its children */
  565.         if ((!S_ISADIR(statInfoPtr->mode)) || (!ignoreDir)) {
  566.             if (*curPath) {
  567.                 statInfoPtr->fileName = Str_Cat(2, curPath, tmpPtr);
  568.             } else {
  569.                 statInfoPtr->fileName = Str_Dup("/");
  570.             }
  571.             retCode = (*receiveProc)(statInfoPtr, receiveBlkPtr);
  572.         }
  573.  
  574.     /* Need to recurse ? */
  575.     if ((fileSpecPtr->recurse > 0) && (S_ISADIR(statInfoPtr->mode)) &&
  576.         (isReadable) && (*statInfoPtr->fileList)) {
  577.         strcpy(newIndx, indxPath);
  578.         strcpy(STRRCHR(newIndx, '/')+1, tmpPtr);
  579.         strcat(newIndx, "/");
  580.         strcat(newIndx, FILESUFFIX);
  581.         newSpec = *fileSpecPtr;
  582.         newSpec.recurse = fileSpecPtr->recurse - 1;
  583.         newSpec.fileName = Str_Dup(statInfoPtr->fileList);
  584.         newSpec.firstVer = -1;
  585.         newSpec.lastVer = -1;
  586. /*
  587.         if (jDebug) {
  588.         fprintf(stderr,"Indx_match: recursing %s\n", 
  589.         newSpec.fileName);
  590.         }
  591. */
  592.         Indx_Match(&newSpec, newIndx, archPath, callerPtr,
  593.                receiveProc, receiveBlkPtr, 0);
  594.         MEM_FREE("Indx_Match", newSpec.fileName);
  595.     }
  596.     Utils_FreeFileStat(statInfoPtr, 1);
  597.     }
  598.  
  599.     Q_Destroy(fileQueue);
  600.     Hash_Destroy(nameTab);
  601.  
  602.     return retCode;
  603.  
  604. }
  605.  
  606.  
  607. /*
  608.  *----------------------------------------------------------------------
  609.  *
  610.  * Indx_MakeIndx --
  611.  *
  612.  *    Create index file path for specified archive and file
  613.  *
  614.  * Results:
  615.  *    returns name of index file.
  616.  *
  617.  * Side effects:
  618.  *    Allocates string space.
  619.  *
  620.  *----------------------------------------------------------------------
  621.  */
  622.  
  623. int
  624. Indx_MakeIndx(archPath, filePath, indxPath)
  625.     char *archPath;           /* name of archive. */
  626.     char *filePath;           /* full path name of file */
  627.     char *indxPath;           /* ptr to receiving space */
  628. {
  629.     char *slashPtr;
  630.  
  631.     if ((slashPtr=STRRCHR(filePath, '/')) == NULL) {
  632.     return T_BADMSGFMT;
  633.     } else {
  634.     strcpy(indxPath, archPath);
  635.     if (*(slashPtr+1)) {
  636.         strcat(indxPath, "/");
  637.         strcat(indxPath, SLASHSUFFIX);
  638.     }
  639.     *slashPtr = '\0';
  640.     strcat(indxPath, filePath);
  641.     strcat(indxPath, "/");
  642.     strcat(indxPath, FILESUFFIX);
  643.     *slashPtr = '/';
  644.     }
  645.     return T_SUCCESS;
  646. }
  647.  
  648.  
  649.  
  650. /*
  651.  *----------------------------------------------------------------------
  652.  *
  653.  * Indx_MakeIndxList --
  654.  *
  655.  *    Read through directory hierarchy finding index files
  656.  *
  657.  * Results:
  658.  *    returns list of index files.
  659.  *
  660.  * Side effects:
  661.  *    none.
  662.  *
  663.  *----------------------------------------------------------------------
  664.  */
  665.  
  666. int
  667. Indx_MakeIndxList(archPath, filePath, indxQueue)
  668.     char *archPath;           /* name of archive. */
  669.     char *filePath;           /* reg exp describing file */
  670.     Q_Handle *indxQueue;      /* work queue to collect index filenames */
  671. {
  672.     char dirPath[2*T_MAXPATHLEN];
  673.     char **partList;
  674.     int partCnt = 0;
  675.     int retCode;
  676.     char *insidePtr;
  677.  
  678.     strcpy(dirPath, archPath);
  679.     if (*(filePath+1)) {
  680.     strcat(dirPath, "/");
  681.     strcat(dirPath, SLASHSUFFIX);
  682.     }
  683.     partList = Str_Split(filePath, '/', &partCnt, 0, &insidePtr);
  684.     partList[partCnt-1] = NULL; /* Zap the simple filename */
  685.     retCode = MatchPath(&partList[1], dirPath, indxQueue);
  686.  
  687.     MEM_FREE("Indx_MakeIndxList", (char *)partList);
  688.     MEM_FREE("Indx_MakeIndxList", (char *)insidePtr);
  689.  
  690.     return retCode;
  691.  
  692. }
  693.  
  694.  
  695. /*
  696.  *----------------------------------------------------------------------
  697.  *
  698.  * MatchPath
  699.  *
  700.  *    Recursively descend through tree matching pathname parts
  701.  *
  702.  * Results:
  703.  *    none.
  704.  *
  705.  * Side effects:
  706.  *    Will put matching names on queue.
  707.  *
  708.  *----------------------------------------------------------------------
  709.  */
  710.  
  711. static int
  712. MatchPath(partList, dirPath, indxQueue)
  713.     char **partList;          /* pathname parts not yet matched */
  714.     char *dirPath;            /* built-up pathname */
  715.     Q_Handle *indxQueue;      /* list of matching filenames */
  716. {
  717.     DIR *dirStream;
  718.     DirObject *entryPtr;
  719.     char *dirPtr;
  720.     struct stat statBuf;
  721.     char *tmpPtr;
  722.     char **newPartList;
  723. /*
  724.     if (jDebug) {
  725.       fprintf(stderr,"partList '%s', dirPath '%s'\n",
  726.           *partList, dirPath);
  727.     }
  728. */
  729.     if (*partList == NULL) {
  730.     newPartList = partList;
  731.     tmpPtr = Str_Cat(3, dirPath, "/", FILESUFFIX);
  732.     Q_Add(indxQueue, (Q_ClientData) tmpPtr, Q_TAILQ);
  733.     return T_SUCCESS;
  734.     } else {
  735.     newPartList = partList+1;
  736.     }
  737.     
  738.     if ((dirStream=opendir(dirPath)) == (DIR *)NULL) {
  739.       if (errno == ENOENT) {
  740.     return T_SUCCESS; /* no index file is ok */
  741.       } else {
  742.     syserr = errno;
  743.     if (jDebug) {
  744.       fprintf(stderr,"MatchPath: couldn't open %s. errno %d\n",
  745.           dirPath, syserr);
  746.     }
  747.     return T_INDXFAILED;
  748.       }
  749.     }
  750.  
  751.     strcat(dirPath, "/");
  752.     dirPtr = dirPath+strlen(dirPath);
  753.  
  754.     while ((entryPtr=readdir(dirStream)) != (DirObject *)NULL) {
  755.     if ((strcmp(entryPtr->d_name, ".") != 0) &&
  756.         (strcmp(entryPtr->d_name, "..") != 0) &&
  757.         ((*partList == NULL) ||
  758.          (Str_Match(entryPtr->d_name, *partList)))) {
  759.         strcpy(dirPtr, entryPtr->d_name);
  760.         if ((stat(dirPath, &statBuf) >= 0) &&
  761.         (S_ISADIR(statBuf.st_mode))) {
  762.         if (MatchPath(newPartList, dirPath, indxQueue) 
  763.             != T_SUCCESS) {
  764.             return T_INDXFAILED;
  765.         }
  766.         }
  767.     }
  768.     }
  769.  
  770.     return T_SUCCESS;
  771. }
  772.  
  773.  
  774.  
  775. /*
  776.  *----------------------------------------------------------------------
  777.  *
  778.  * IsReadable --
  779.  *
  780.  *    Check for proper read permission.
  781.  *
  782.  * Results:
  783.  *    1 == readable; 0 = protected.
  784.  *
  785.  * Side effects:
  786.  *    None.
  787.  *
  788.  *----------------------------------------------------------------------
  789.  */
  790.  
  791. static int
  792. IsReadable(statInfoPtr, caller)
  793.     T_FileStat *statInfoPtr;  /* file in question */
  794.     Caller *caller;           /* caller's id */
  795. {
  796.     if ((statInfoPtr->mode & 04) ||
  797.     (Str_Match(statInfoPtr->uname, caller->userName)) ||
  798.     (Str_Match(statInfoPtr->gname, caller->groupName) &&
  799.      (statInfoPtr->mode & 040))) {
  800.     return 1;
  801.     }
  802.     if (jDebug) {
  803.     fprintf(stderr,"No Access: %s ('%s %s 0%o' != '%s %s')\n",
  804.         statInfoPtr->fileName, statInfoPtr->uname,
  805.         statInfoPtr->gname, statInfoPtr->mode,
  806.         caller->userName, caller->groupName);
  807.     }
  808.  
  809.     return 0;
  810. }
  811.  
  812.  
  813. /*
  814.  *----------------------------------------------------------------------
  815.  *
  816.  * ReadIndxFile --
  817.  *
  818.  *    Read and store contents of an indx file.
  819.  *
  820.  * Results:
  821.  *    returns list T_FileStat ptrs.
  822.  *
  823.  * Side effects:
  824.  *      May allocate some space. May read indx file.
  825.  *
  826.  *----------------------------------------------------------------------
  827.  */
  828.  
  829. static int
  830. ReadIndxFile(indxPath, fileListPtr, cntPtr)
  831.     char *indxPath;           /* Index file to be read */
  832.     T_FileStat **fileListPtr; /* receiving list ptr */
  833.     int *cntPtr;              /* receiving count ptr */
  834. {
  835.     int i;
  836.     FILE *indxStream;
  837.     int retCode;
  838.     T_FileStat *statInfoPtr;
  839.     static char savedIndxPath[2*T_MAXPATHLEN];
  840.     static T_FileStat *savedFileList = NULL;
  841.     static int savedListSize = 0;
  842.     static int savedFileCnt = 0;
  843.     int newListSize;
  844.     T_FileStat *newFileList;
  845.  
  846.     /*
  847.      * If requested file is the one we have stored, then there's nothing to do.
  848.      * The file may have been changed during our update operation, but
  849.      * it's too costly to do repeated stat operations just to catch this case.
  850.      * Nobody else can be updating this file so we'd only be checking our
  851.      * own updates and few users will do: 'jput file file'
  852.      */
  853.     if (strcmp(indxPath, savedIndxPath) == 0) {
  854. /*
  855.         fprintf(stderr,"Same indx file: %s\n", indxPath);
  856. */
  857.         *fileListPtr = savedFileList;
  858.         *cntPtr = savedFileCnt;
  859.         return T_SUCCESS;
  860.     }
  861.  
  862.     /* release old entries */
  863. /*
  864.     fprintf(stderr,"Freeing indx file: %s, %d entries\n", indxPath, savedFileCnt);
  865. */
  866.     for (i=0,statInfoPtr=savedFileList; i<savedFileCnt; i++,statInfoPtr++) {
  867.         Utils_FreeFileStat(statInfoPtr, 0);
  868.     }
  869.  
  870.     strcpy(savedIndxPath, indxPath);
  871.     *cntPtr = savedFileCnt = 0;
  872.     *fileListPtr = NULL;
  873.  
  874.     /* Attempt the open */
  875.     if ((retCode=Indx_Open(indxPath, "r", &indxStream)) != T_SUCCESS) {
  876.     fprintf(stderr,"Indx_Match: couldn't open %s\n", indxPath);
  877.     return retCode;
  878.     }
  879.  
  880.     /* file does not exist */
  881.     if (indxStream == NULL) {
  882.     return T_SUCCESS;
  883.     }
  884.  
  885.     while (1) {
  886.     /* Make room in the list */
  887.     if (savedFileCnt >= savedListSize) {
  888.         newListSize = savedListSize + 500;
  889.         newFileList = (T_FileStat *)MEM_ALLOC("ReadIndxFile",
  890.                       newListSize*sizeof(T_FileStat));
  891. /*
  892.             fprintf(stderr,"Enlarging indx table space from %d to %d\n",
  893.             savedListSize, newListSize);
  894. */
  895.         for (i=0; i<savedListSize; i++) {
  896.         newFileList[i] = savedFileList[i];
  897.         }
  898.         if (savedFileList != NULL) {
  899.         MEM_FREE("ReadIndxFile", savedFileList);
  900.         }
  901.         savedListSize = newListSize;
  902.         savedFileList = newFileList;
  903.     }
  904.     if ((retCode=Indx_ReadIndxEntry(indxStream,
  905.                &savedFileList[savedFileCnt])) != T_SUCCESS) {
  906.         if ((jDebug) && (retCode != T_FAILURE)) {
  907.         fprintf(stderr,"ReadIndxEntry failed for %s\n", indxPath);
  908.         }
  909.         break;
  910.     }
  911.     savedFileCnt++;
  912.     }
  913.  
  914.     Indx_Close(indxStream);
  915. /*
  916.     fprintf(stderr,"Refilled indx table with %d entries.\n", savedFileCnt);
  917. */
  918.     *fileListPtr = savedFileList;
  919.     *cntPtr = savedFileCnt;
  920.  
  921.     return T_SUCCESS;
  922. }
  923.          
  924.  
  925. /*
  926.  *----------------------------------------------------------------------
  927.  *
  928.  * ReadStringItem --
  929.  *
  930.  *    Read a '\n' terminated string item from index file.
  931.  *
  932.  * Results:
  933.  *    returns duplicated copy of string.
  934.  *
  935.  * Side effects:
  936.  *      May allocate some space.
  937.  *
  938.  *----------------------------------------------------------------------
  939.  */
  940.  
  941. static char *
  942. ReadStringItem(indxStream)
  943.     FILE *indxStream;         /* input stream */
  944. {
  945.     char *string;
  946.     int stringLen;
  947.     char *ptr;
  948.  
  949.     if (fscanf(indxStream, "%x%*c", &stringLen) != 1) {
  950.     fprintf(stderr,"Didn't get string len\n");
  951.     return NULL;
  952.     }
  953.     if ((stringLen < 0) || (stringLen > 1000000)) {
  954.     fprintf(stderr,"got bad string len 0x%x\n", stringLen);
  955.     return NULL;
  956.     }
  957.  
  958.     string = ptr =(char *)MEM_ALLOC("ReadStringItem", (stringLen+1)*sizeof(char));
  959.  
  960.     while (stringLen-- > 0) {
  961.     *ptr++ = (char) getc(indxStream);
  962.     }
  963.  
  964.     *ptr = '\0';
  965.  
  966.     if (getc(indxStream) != (int)'\n') {
  967.     MEM_FREE("ReadStringItem", string);
  968.     fprintf(stderr,"Didn't get final 'cr'\n");
  969.     return NULL;
  970.     }
  971.  
  972.     return string;
  973. }
  974.  
  975.